// LemCoop
// Copyright (C) 2013  Oliver Naumann <bldrax@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef LEMC_SPRITE_H
#define LEMC_SPRITE_H

#include <vector>
#include <boost/lexical_cast.hpp>

#include "../util/logmanager.h"
#include "animation.h"

/*
* A class for sprites. A sprite is an object with various animations (may be only a sinlge one). It has an integer
* position on the screen and varoius other attributes like scale and opacity. A sprite can have one animation at a
* time running, however, there is the possibility to interrupt that animation for playing a different animation
* exactly one time before returning to the main animation.
*/
class Sprite
{
private:
	// The animations of the sprite.
	std::vector<Animation> m_animations;

	// The opacity used to draw the sprite with.
	float m_opacity;

	// The scaling factor used to draw the sprite with (in both x and y direction).
	float m_scale;

	// The x coordinate on the screen. This has likely to be set anew on each frame to account for movement.
	int m_x;
	
	// The y coordinate on the screen. This has likely to be set anew on each frame to account for movement.
	int m_y;

	// The number of the animation that the sprite is currently showing.
	unsigned m_current_animation;

	// True if the animation should be played, i.e. ticked with every update()
	bool m_current_animation_running;

	// True if an animation is currently running that is played only once.
	bool m_in_single_animation;

	//The number of the animation that is played once.
	unsigned m_single_animation;

	//True if this sprite has any animation at all.
	bool m_has_graphics;

public:
	/*
	* Constructs a sprite without animations. This still sets all necessary standard parameters like the position,
	* the scaling and the opacity.
	*/
	Sprite();

	/*
	* Constructs a sprite with exactly one animation and also initializes the standard parameters like the position,
	* the scaling and the ocacity.
	*
	* @param first_animation The first animation of the sprite.
	* @param first_animation_running Set this to true if you want to have the animation being played from the
	* beginning on. If this is false, the animation has to be started later. This should of course remain false is
	* the animation consists only of a single frame.
	*/
	Sprite(Animation first_animation, bool first_animation_running);

	/*
	* Adds an animation to the sprite.
	*
	* @param animation The animation to be added.
	*/
	void AddAnimation(Animation animation);

	/*
	* Sets the animation which is to be shown.
	*
	* @param number The number of the animation to be shown.
	* 
	* @return True if the new animation could be set, false if that was not possible, e.g. the number was bigger than
	* the number of animations avaiable.
	*/
	bool SetCurrentAnimation(unsigned number);

	/*
	* Sets the animation to be played, which means that each frame the sprite will tick it and thereby have it run.
	*/
	void PlayAnimation();

	/*
	* Stops animations from being played for this sprite.
	*/
	void StopAnimation();

	/*
	* Resets the current animation, which is propagated directly to the animation, which then resets its ticks and
	* goes back to its first element.
	*/
	void ResetCurrentAnimation();

	/*
	* Plays an animation exactly once. This means that the current animation will be interrupted and the animation
	* to be played once starts. The Update() method will then detect when the animation has played completely and
	* return to the old animation automatically. If this function is called when an animation to be played once is
	* already playing, it is simple replaced by the new one.
	*
	* @param number The number of the animation to be played once.
	*
	* @return True if the new animation could be set, false if that was not possible, e.g. the number was bigger than
	* the number of animations avaiable.
	*/
	bool PlayAnimationOnce(unsigned number);

	/*
	* Updates the sprite. Especially that means that the animation is ticked if it is being played, but it is also
	* detected whether an animation to be played once has ended.
	*/
	void Update(float timing_factor);

	/*
	* Draws the sprite.
	*/
	void Draw();

	void set_x(int x) { m_x = x; }
	void set_y(int y) { m_y = y; }
	void set_opacity(float opacity) { m_opacity = opacity; }
	void set_scale(float scale) { m_scale = scale; }

	bool has_graphics() { return m_has_graphics; }
};

#endif